package com.github.wui.comm;

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
import com.github.wui.R;

/**
 * 无缝循环跑马灯 · 尾部与下一次头部固定间距
 * 1. 永远不从 0 复位，仅靠坐标回退实现循环
 * 2. 支持 XML 属性：speed、gapDp
 * 3. 支持代码动态换文字、改速度、改间距
 */
class MarqueeTextView @JvmOverloads constructor(
    ctx: Context, attrs: AttributeSet? = null
) : AppCompatTextView(ctx, attrs), Runnable {

    private var paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        isAntiAlias = true
        isDither = true
    }

    private var text = ""
    private var textWidth = 0f
    private var drawX = 0f          // 第一份文字左侧坐标
    private var speedPx = 0f        // 每帧移动的 px（>0 向左）
    private var gapPx = 0f          // 尾部与下一次头部的间距 px
    private var _drawX = 0f
    init {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.MarqueeTextView)
        val speedDp = ta.getFloat(R.styleable.MarqueeTextView_mtv_speed, 60f)  // dp/s
        val gapDp = ta.getFloat(R.styleable.MarqueeTextView_mtv_gapDp, 48f)    // dp
        speedPx = speedDp * resources.displayMetrics.density / 60f         // 60 fps
        gapPx = gapDp * resources.displayMetrics.density
        ta.recycle()

        setSingleLine()
        ellipsize = null
        paint.color = currentTextColor
        paint.textSize = textSize
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        drawX = w.toFloat()          // 从右侧进入
    }

    override fun onDraw(canvas: Canvas) {
        if (text.isEmpty()) return
        val baseline = height / 2f - (paint.descent() + paint.ascent()) / 2f

        // 画两份：第二份紧跟第一份 + gap
        canvas.drawText(text, drawX, baseline, paint)
        canvas.drawText(text, drawX + textWidth + gapPx, baseline, paint)

        // 当第一份尾部完全离开屏幕，把坐标拉回（textWidth + gapPx）实现循环
        if (drawX + textWidth < -gapPx) {
            drawX += textWidth + gapPx
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        post(this)
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        removeCallbacks(this)
    }

    override fun run() {
        drawX -= speedPx
        invalidate()
        postDelayed(this, 16) // 60 fps
    }

    /* 对外暴露：动态换文字 */
    fun setMarqueeText(newText: String) {
        paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            isAntiAlias = true
            isDither = true
        }
        paint.color = currentTextColor
        paint.textSize = textSize
        text = newText
        textWidth = paint.measureText(text)
        drawX = width.toFloat()
        invalidate()
    }


    fun setSpeed(dpPerSecond: Float) {
        speedPx = dpPerSecond * resources.displayMetrics.density / 60f
    }

    fun setGap(dp: Float) {
        gapPx = dp * resources.displayMetrics.density
    }

    override fun onTextChanged(
        t: CharSequence?,
        start: Int,
        lengthBefore: Int,
        lengthAfter: Int
    ) {
        super.onTextChanged(t, start, lengthBefore, lengthAfter)

        setMarqueeText(t?.toString() ?: "")
    }
}